package controller;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import model.AfbeeldingItem;
import model.Constants;
import model.ItemKenmerken;
import model.ItemNiveau;
import model.Presentatie;
import model.Presenteerbaar;
import model.Slide;
import model.SlideItem;
import model.TekstItem;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import view.HoofdScherm;
import view.themas.ThemaFactory;

/**
 * Deze klasse is verantwoordelijk voor het opslaan en bewaren van een
 * presentatie in XML
 */

public class XMLOpslag implements Opslag {

	@Override
	public void bewaarPresentatie(File file) throws IOException {

		// Als geen bestandsnaam wordt opgegeven, keer dan terug
		if (file == null) {
			return;
		}

		PrintWriter out = null;

		try {
			FileWriter writer = new FileWriter(file);
			out = new PrintWriter(writer);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null,
					Constants.FOUT + e.getMessage(), Constants.FOUTTITEL,
					JOptionPane.ERROR_MESSAGE);
		}

		out.println("<?xml version=\"1.0\"?>");
		out.println("<!DOCTYPE presentatie SYSTEM \"presentatie.dtd\">");
		out.println("<presentatie>");
		out.println("<thema>");
		out.println(PresentatieController.presentatie.getThema().getThemaNaam());
		out.println("</thema>");

		// We gaan elke slide af
		for (Presenteerbaar item : PresentatieController.presentatie.getItems()) {

			Slide slide = (Slide) item;
			out.println("<slide>");

			// en daarvan elk slideItem
			for (Presenteerbaar item2 : slide.getItems()) {

				out.println("<slideItem>");
				out.println("<specialItem>");
				out.println(item.getKenmerken().getSpeciaalItem());
				out.println("</specialItem>");

				SlideItem slideItem = (SlideItem) item2;
				if (slideItem instanceof TekstItem) {
					out.println("<soortItem>");
					out.println(Constants.TEKST_ITEM);
					out.println("</soortItem>");
					out.println("<tekst>");
					out.println(((TekstItem) slideItem).getTekst());
					out.println("</tekst>");

				} else {
					out.println("<soortItem>");
					out.println(Constants.AFBEELDING_ITEM);
					out.println("</soortItem>");
					out.println("<locatie>");
					out.println(((AfbeeldingItem) slideItem)
							.getAfbeeldingLocatie());
					out.println("</locatie>");
				}
				out.println("<niveau>");
				out.println(slideItem.getKenmerken().getNiveau().getValue());
				out.println("</niveau>");
				out.println("</slideItem>");
			}
			out.println("</slide>");
		}
		out.println("</presentatie>");
		out.close();

		JOptionPane.showMessageDialog(null,
				Constants.PRESENTATIE + file.getName() + Constants.BEWAARD);
	}

	// laadt een presentatie dat in XML formaat is opgeslagen
	@Override
	public void laadPresentatie(File file) {

		Presentatie presentatie = new Presentatie();
		SlideItemFactory slideItemFactory = new SlideItemFactory();
		ThemaFactory themaFactory = new ThemaFactory();
		boolean demo = false;

		// Als er geen bestandsnaam is opgegeven,wordt de demo geladen
		if (file == null) {
			file = new File(Constants.DEMO_BESTAND_XML);
			JOptionPane.showMessageDialog(null, Constants.DEMO_LADEN);
		}

		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(file);
			doc.getDocumentElement().normalize();

			String thema = null;
			String speciaalItem = null;
			String niveau = null;
			String soortItem = null;

			thema = (getValue("thema",
					(Element) (doc.getElementsByTagName("thema")).item(0)
							.getParentNode()));

			switch (thema) {
			case (Constants.STANDAARDTHEMA):
				presentatie.setThema(themaFactory.createDefaultThema());
				break;
			case (Constants.COLORFULLTHEMA):
				presentatie.setThema(themaFactory.createColorFullThema());
				break;
			case (Constants.COMPLEXTHEMA):
				presentatie.setThema(themaFactory.createComplexThema());
				break;
			default:
				presentatie.setThema(themaFactory.createDefaultThema());
			}

			NodeList slideLst = doc.getElementsByTagName("slide");

			for (int s = 0; s < slideLst.getLength(); s++) {
				Node node = slideLst.item(s);

				if (node.getNodeType() == Node.ELEMENT_NODE) {
					Element element = (Element) node;

					Slide slide = new Slide();
					ItemKenmerken itemKenmerken = new ItemKenmerken();
					itemKenmerken.setNiveau(ItemNiveau.Slide);
					itemKenmerken.setSpeciaalItem(false);
					slide.setKenmerken(itemKenmerken);

					NodeList slideItemLst = node.getChildNodes();
					for (int t = 0; t < slideItemLst.getLength(); t++) {
						SlideItem slideItem = null;
						itemKenmerken = new ItemKenmerken();
						Node slideItemNode = slideItemLst.item(t);
						if (slideItemNode.getNodeType() == Node.ELEMENT_NODE) {

							Element slideItemElement = (Element) slideItemNode;
							speciaalItem = getValue("specialItem",
									slideItemElement);
							if (speciaalItem.equals(Constants.FALSE)) {
								itemKenmerken.setSpeciaalItem(false);
							} else {
								itemKenmerken.setSpeciaalItem(true);
							}
							soortItem = getValue("soortItem", slideItemElement);
							switch (soortItem) {
							case (Constants.TEKST_ITEM):
								slideItem = slideItemFactory
										.createTekstItem(getValue("tekst",
												slideItemElement));
								break;
							case (Constants.AFBEELDING_ITEM):
								slideItem = slideItemFactory
										.createAfbeeldingItem(getValue(
												"locatie", slideItemElement));
								break;
							default:
							}

							niveau = getValue("niveau", slideItemElement);
							switch (niveau) {
							case ("3"):
								itemKenmerken.setNiveau(ItemNiveau.Titel);
								break;
							case ("4"):
								itemKenmerken.setNiveau(ItemNiveau.Niveau1Item);
								break;
							case ("5"):
								itemKenmerken.setNiveau(ItemNiveau.Niveau2Item);
								break;
							case ("6"):
								itemKenmerken.setNiveau(ItemNiveau.Niveau3Item);
								break;
							}
							slideItem.setKenmerken(itemKenmerken);
							slide.voegItemToe(slideItem);
						}

					}
					presentatie.voegItemToe(slide);
				}
				// We zetten het thema nog eens om het composite pattern zijn
				// werk te laten doen
				presentatie.setThema(presentatie.getThema());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		PresentatieController.presentatie = presentatie;
		presentatie.addObserver(HoofdScherm.getInstance());
		presentatie.gaNaar(1);
		HoofdScherm.getInstance().setTitelPresentatie(file.getName());
		
		if (!demo) {
			JOptionPane.showMessageDialog(HoofdScherm.getInstance(),
					Constants.PRESENTATIE + file.getName() + Constants.GELADEN);
		}

	}

	// hulpmethode om een waarde van een XML tag in te lezen
	private String getValue(String tag, Element element) {

		NodeList nodes = element.getElementsByTagName(tag).item(0)
				.getChildNodes();
		Node node = (Node) nodes.item(0);
		return node.getNodeValue().trim();

	}

}
